package com.one.group.admin.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.tenant.TenantManager;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.one.group.admin.mapper.EquipmentMapper;
import com.one.group.admin.mapper.MaintenanceUnitInfoMapper;
import com.one.group.admin.mapper.RepairRecordMapper;
import com.one.group.enums.ErrorCode;
import com.one.group.model.dto.EquipmentAddDto;
import com.one.group.model.dto.EquipmentQueryDto;
import com.one.group.model.dto.EquipmentUpdateDto;
import com.one.group.model.entity.Equipment;
import com.one.group.model.entity.MaintenanceUnitInfo;
import com.one.group.model.vo.EquipmentInfoVo;
import com.one.group.model.vo.EquipmentVo;
import com.one.group.service.EquipmentService;
import com.one.group.utils.ThrowUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * {@code @Create:}  2025-09-28  14 : 52
 * {@code @Author:} Cherry
 * {@code @ToUser:} 凡是发生,皆有利于我。
 * ------------------------------------
 * {@code @note:}
 */

@Slf4j
@SuppressWarnings({"all"})
@Service
public class EquipmentServiceImpl extends ServiceImpl<EquipmentMapper, Equipment> implements EquipmentService {
    @Resource
    private EquipmentMapper equipmentMapper;
    @Resource
    private MaintenanceUnitInfoMapper maintenanceUnitInfoMapper;
    @Resource
    private RepairRecordMapper repairRecordMapper;

    @Override
    public List<EquipmentVo> findEquipmentByQueryDto(EquipmentQueryDto equipmentQueryDto) {
        Long aLong = Convert.toLong(StpUtil.getExtra("tenant_id"));
        log.debug("tenantid:{}", aLong);
        equipmentQueryDto.setTenantId(Convert.toLong(StpUtil.getExtra("tenant_id")));
        List<EquipmentVo> equipmentByQueryDto = equipmentMapper.findEquipmentByQueryDto(equipmentQueryDto);
        return equipmentByQueryDto;
    }

    @Override
    @Transactional
    public boolean addEquipmentByAddDto(EquipmentAddDto equipmentAddDto) {
        String deviceName = equipmentAddDto.getDeviceName();
        String deviceCode = equipmentAddDto.getDeviceCode();
        String deviceType = equipmentAddDto.getDeviceType();
        String deviceMaterial = equipmentAddDto.getDeviceMaterial();
        String deviceWeight = equipmentAddDto.getDeviceWeight();
        BigDecimal price = equipmentAddDto.getPrice();
        String unit = equipmentAddDto.getUnit();
        int deviceStock = equipmentAddDto.getDeviceStock();
        int status = equipmentAddDto.getStatus();
        Date installDate = equipmentAddDto.getInstallDate();
        String installAddress = equipmentAddDto.getInstallAddress();
        String manufacturer = equipmentAddDto.getManufacturer();
        String manufacturerAddress = equipmentAddDto.getManufacturerAddress();
        String manufacturerPhone = equipmentAddDto.getManufacturerPhone();
        String responsiblePerson = equipmentAddDto.getResponsiblePerson();

        String maintenanceUnit = equipmentAddDto.getMaintenanceUnit();
        String maintenanceUnitPhone = equipmentAddDto.getMaintenanceUnitPhone();
        String maintenanceUnitAddress = equipmentAddDto.getMaintenanceUnitAddress();
        String equipmentMaintainer = equipmentAddDto.getEquipmentMaintainer();
        Date registrationDate = equipmentAddDto.getRegistrationDate();
        String remarks = equipmentAddDto.getRemarks();

        //设备表插入数据
        Long equipmentId = equipmentAdd(equipmentAddDto, deviceName, deviceCode, deviceType, deviceMaterial, deviceWeight, price, unit, deviceStock,
                status,
                installDate, installAddress, manufacturer, responsiblePerson, manufacturerAddress, manufacturerPhone);

        ThrowUtil.throwIf(equipmentId == null, ErrorCode.OPERATION_ERROR);

        maintenanceRecordAdd(maintenanceUnitAddress, maintenanceUnitPhone, maintenanceUnit, remarks, registrationDate, equipmentMaintainer, equipmentId);
        return true;
    }

    @Override
    @Transactional
    public boolean updateEquipmentByUpdateDto(EquipmentUpdateDto equipmentUpdateDto) {
        TenantManager.ignoreTenantCondition();
        //设备表
        Long id = equipmentUpdateDto.getId();
        String deviceName = equipmentUpdateDto.getDeviceName();
        String deviceCode = equipmentUpdateDto.getDeviceCode();
        String deviceType = equipmentUpdateDto.getDeviceType();
        String deviceMaterial = equipmentUpdateDto.getDeviceMaterial();
        String deviceWeight = equipmentUpdateDto.getDeviceWeight();
        BigDecimal price = equipmentUpdateDto.getPrice();
        String unit = equipmentUpdateDto.getUnit();
        int deviceStock = equipmentUpdateDto.getDeviceStock();
        int status = equipmentUpdateDto.getStatus();
        Date installDate = equipmentUpdateDto.getInstallDate();
        String installAddress = equipmentUpdateDto.getInstallAddress();
        String manufacturer = equipmentUpdateDto.getManufacturer();
        String manufacturerAddress = equipmentUpdateDto.getManufacturerAddress();
        String manufacturerPhone = equipmentUpdateDto.getManufacturerPhone();
        String responsiblePerson = equipmentUpdateDto.getResponsiblePerson();
        //维护单位表
        String maintenanceUnit = equipmentUpdateDto.getMaintenanceUnit();
        String maintenanceUnitPhone = equipmentUpdateDto.getMaintenanceUnitPhone();
        String maintenanceUnitAddress = equipmentUpdateDto.getMaintenanceUnitAddress();
        String equipmentMaintainer = equipmentUpdateDto.getEquipmentMaintainer();
        Date registrationDate = equipmentUpdateDto.getRegistrationDate();
        String remarks = equipmentUpdateDto.getRemarks();


        equipmentUpdate(id, deviceName, deviceCode, deviceType, deviceMaterial, deviceWeight, price, unit, deviceStock, status,
                installDate, installAddress, manufacturer, responsiblePerson, manufacturerAddress, manufacturerPhone);

        maintenanceUnitUpdate(id, maintenanceUnit, maintenanceUnitPhone, maintenanceUnitAddress, equipmentMaintainer, registrationDate, remarks, id);

        return true;

    }

    @Override
    @Transactional
    public boolean deleteEquipmentByIds(Long id) {
        equipmentMapper.deleteById(id);

        maintenanceUnitInfoMapper.deleteByQuery(new QueryWrapper().eq(MaintenanceUnitInfo::getEquipmentId, id));
        return true;
    }

    @Override
    @Transactional
    public boolean deleteEquipmentWithMantenanceByIds(List<Long> ids) {
        ids.forEach(id -> {
            equipmentMapper.deleteById(id);
            maintenanceUnitInfoMapper.deleteByQuery(new QueryWrapper().eq(MaintenanceUnitInfo::getEquipmentId, id));
        });
        return true;
    }

    @Override
    public EquipmentInfoVo getOneInfoById(Long id) {
        return equipmentMapper.getInfoById(id, Convert.toLong(StpUtil.getExtra("tenant_id")));
    }

    private void maintenanceUnitUpdate(Long id, String maintenanceUnit, String maintenanceUnitPhone, String maintenanceUnitAddress,
                                       String equipmentMaintainer, Date registrationDate, String remarks, Long equipmentId) {
        MaintenanceUnitInfo maintenanceUnitInfo =
                MaintenanceUnitInfo.builder()
                        .id(id)
                        .maintenanceUnit(maintenanceUnit)
                        .maintenanceUnitAddress(maintenanceUnitAddress)
                        .maintenanceUnitPhone(maintenanceUnitPhone)
                        .equipmentMaintainer(equipmentMaintainer)
                        .remarks(remarks)
                        .equipmentId(equipmentId)
                        .build();
        QueryWrapper wrapper = new QueryWrapper().eq(MaintenanceUnitInfo::getEquipmentId, equipmentId);
        maintenanceUnitInfoMapper.updateByQuery(maintenanceUnitInfo, wrapper);
    }

    private void equipmentUpdate(Long id, String deviceName, String deviceCode, String deviceType, String deviceMaterial, String deviceWeight, BigDecimal price, String unit, int deviceStock, int status, Date installDate, String installAddress, String manufacturer, String responsiblePerson, String manufacturerAddress, String manufacturerPhone) {
        Equipment equipment = Equipment.builder()
                .id(id)
                .deviceName(deviceName)
                .deviceCode(deviceCode)
                .deviceType(deviceType)
                .deviceMaterial(deviceMaterial)
                .deviceWeight(deviceWeight)
                .price(price)
                .unit(unit)
                .deviceStock(deviceStock)
                .status(status)
                .installDate(installDate)
                .installAddress(installAddress)
                .manufacturer(manufacturer)
                .manufacturerAddress(manufacturerAddress)
                .manufacturerPhone(manufacturerPhone)
                .build();

        // 1. 先查询是否有其他记录使用相同的 deviceCode
        QueryWrapper wrapper = new QueryWrapper().eq(Equipment::getDeviceCode, deviceCode).ne(Equipment::getId, id);

        // 2. 如果有则抛出异常
        Equipment existing = equipmentMapper.selectOneByQuery(wrapper);

        ThrowUtil.throwIf(existing != null, ErrorCode.PARAMS_ERROR, "设备编码已存在");

        // 3. 否则更新
        equipmentMapper.update(equipment);
    }

    private void maintenanceRecordAdd(String maintenanceUnitAddress, String maintenanceUnitPhone, String maintenanceUnit,
                                      String remarks, Date registrationDate, String equipmentMaintainer, Long equipmentId) {
        MaintenanceUnitInfo maintenanceUnitInfo = MaintenanceUnitInfo.builder()
                .maintenanceUnitAddress(maintenanceUnitAddress)
                .maintenanceUnitPhone(maintenanceUnitPhone)
                .maintenanceUnit(maintenanceUnit)
                .equipmentId(equipmentId)
                .remarks(remarks)
                .equipmentMaintainer(equipmentMaintainer)
                .registrationDate(registrationDate)
                .build();

        maintenanceUnitInfoMapper.insert(maintenanceUnitInfo);
    }

    private Long equipmentAdd(EquipmentAddDto equipmentAddDto, String deviceName, String deviceCode, String deviceType, String deviceMaterial,
                              String deviceWeight, BigDecimal price, String unit, int deviceStock, int status, Date installDate,
                              String installAddress, String manufacturer, String responsiblePerson, String manufacturerAddress, String manufacturerPhone) {
        QueryWrapper wrapper = new QueryWrapper().eq(Equipment::getDeviceCode, equipmentAddDto.getDeviceCode());
        //设备编码唯一不能重复添加
        Equipment equipment = equipmentMapper.selectOneByQuery(wrapper);
        ThrowUtil.throwIf(equipment != null, ErrorCode.Data_CODE_EXITS);

        //往设备表插入数据
        Equipment newEquipment = Equipment.builder()
                .tenantId(Convert.toLong(StpUtil.getExtra("tenant_id")))
                .deviceName(deviceName)
                .deviceCode(deviceCode)
                .deviceType(deviceType)
                .deviceMaterial(deviceMaterial)
                .deviceWeight(deviceWeight)
                .price(price)
                .unit(unit)
                .deviceStock(deviceStock)
                .status(status)
                .installDate(installDate)
                .installAddress(installAddress)
                .manufacturer(manufacturer)
                .manufacturerAddress(manufacturerAddress)
                .manufacturerPhone(manufacturerPhone)
                .build();

        equipmentMapper.insertEquipment(newEquipment);
        return newEquipment.getId();
    }
}
